#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SHM_KEY 1234
#define SEM_KEY 5678

// 信号量操作函数
int semaphore_wait(int semid) {
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = -1; // P 操作
    sb.sem_flg = 0;
    return semop(semid, &sb, 1);
}

int semaphore_signal(int semid) {
    struct sembuf sb;
    sb.sem_num = 0;
    sb.sem_op = 1; // V 操作
    sb.sem_flg = 0;
    return semop(semid, &sb, 1);
}

int main() {
    int shmid, semid;
    int *shm_ptr;
    pid_t pid;

    // 创建共享内存
    shmid = shmget(SHM_KEY, sizeof(int), 0666 | IPC_CREAT);
    if (shmid == -1) {
        perror("shmget");
        exit(EXIT_FAILURE);
    }

    // 创建信号量
    semid = semget(SEM_KEY, 1, 0666 | IPC_CREAT);
    if (semid == -1) {
        perror("semget");
        exit(EXIT_FAILURE);
    }

    // 初始化信号量
    if (semaphore_signal(semid) == -1) {
        perror("semaphore_signal");
        exit(EXIT_FAILURE);
    }

    // 创建两个子进程
    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) { // 子进程 P1
        shm_ptr = (int *)shmat(shmid, NULL, 0);
        if (shm_ptr == (int *)-1) {
            perror("shmat");
            exit(EXIT_FAILURE);
        }

        for (int i = 1; i <= 10; i++) {
            semaphore_wait(semid); // 等待信号量
            *shm_ptr = i;          // 写入共享内存
            printf("P1: Sent %d\n", i);
            semaphore_signal(semid); // 释放信号量
            sleep(1);              // 模拟处理时间
        }

        shmdt(shm_ptr); // 分离共享内存
        exit(0);
    } else { // 父进程
        pid = fork();
        if (pid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        }

        if (pid == 0) { // 子进程 P2
            shm_ptr = (int *)shmat(shmid, NULL, 0);
            if (shm_ptr == (int *)-1) {
                perror("shmat");
                exit(EXIT_FAILURE);
            }

            for (int i = 1; i <= 10; i++) {
                semaphore_wait(semid); // 等待信号量
                printf("P2: Received %d\n", *shm_ptr);
                semaphore_signal(semid); // 释放信号量
                sleep(1);               // 模拟处理时间
            }

            shmdt(shm_ptr); // 分离共享内存
            exit(0);
        } else { // 父进程
            wait(NULL); // 等待第一个子进程结束
            wait(NULL); // 等待第二个子进程结束

            // 清理 IPC 资源
            shmctl(shmid, IPC_RMID, 0);
            semctl(semid, 0, IPC_RMID);
            printf("Parent: IPC resources cleaned up.\n");
        }
    }

    return 0;
}